﻿using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using TFSTeamCityNotify.Entities;

namespace TFSTeamCityNotify
{
    /// <summary>
    /// Summary description for Integration
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class Integration : WebService
    {
        private string teamcityServer { get; set; }
        private string username { get; set; }
        private string password { get; set; }

        public void ExecuteBuild(string tcusername, string tcpassword, string url)
        {
            try
            {

                string credentials = String.Format("{0}:{1}", tcusername, tcpassword);
                byte[] bytes = Encoding.ASCII.GetBytes(credentials);
                string base64 = Convert.ToBase64String(bytes);
                string authorization = String.Concat("basic ", base64);

                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Credentials = new NetworkCredential(username, password);
                request.Headers.Add("Authorization", authorization);

                var response = (HttpWebResponse)request.GetResponse();
            }
            catch (Exception)
            {
                // since this is happening in a background thread, we dont 
                // want to halt any processes with a hung exception - just skip any errors
                // maybe later we will report them if neccessary
            }

        }

        public T LoadDataFile<T>(string filePath)
        {
            if (File.Exists(filePath))
            {
                try
                {
                    var document = new XmlDocument();
                    document.Load(filePath);

                    return Serializer.Deserialize<T>(document.InnerXml);
                }
                catch (Exception)
                {
                    throw new InvalidOperationException(filePath + " does not exist, fool!");
                }
            }

            return default(T);
        }

        [SoapDocumentMethod(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
        [WebMethod(MessageName = "Notify")]
        public void Notify(string eventXml)
        {
            teamcityServer = ConfigurationManager.AppSettings["TeamcityServer"];
            username = ConfigurationManager.AppSettings["Username"];
            password = ConfigurationManager.AppSettings["Password"];

            try
            {
                var eventDoc = new XmlDocument();

                // load up the results
                eventDoc.LoadXml(eventXml.ToLower());

                // load up the vcs config 
                var vcsCollection = LoadDataFile<VCSCollection>(HttpContext.Current.Request.MapPath("VCS.config"));
                var navigator = eventDoc.CreateNavigator();

                // loop all of the vcs objects in the collection
                foreach (VCS vcs in vcsCollection)
                {
                    // check to see if we have exclusions
                    if (vcs.Exclusions != null)
                    {
                        // loop the exclusion paths
                        foreach (var path in vcs.Exclusions.Paths)
                        {
                            // get a list of excluded files for this path
                            var excludeIterator = navigator.Select(string.Format("checkinevent/artifacts/artifact[@serveritem[contains(.,'{0}')]]/.", vcs.Folder.ToLower() + path.ToLower()));

                            // remove them  from the document
                            while (excludeIterator.MoveNext())
                                if(excludeIterator.Current != null) 
                                    excludeIterator.Current.DeleteSelf();
                        }
                    }

                    // check to see if the current vcs folder was checked into
                    if (navigator.SelectSingleNode(string.Format("checkinevent/artifacts/artifact[@folder[starts-with(.,'{0}')]]/.", vcs.Folder.ToLower())) != null)
                    {
                        // execute all of th ebuilds in the build type collection
                        foreach (var buildTypeID in vcs.BuildTypes.BuildTypeIDs)
                            ExecuteBuild(username, password, string.Format(teamcityServer, buildTypeID));
                    }
                }
            }
            catch (Exception)
            {
                // we will eventually add in some trace logging
            }
        }
    }
}
